<!--
Copyright 2023 Google LLC

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->

<head>
  <!--<meta name="viewport" content="width=device-width, initial-scale=1">-->
<meta charset="utf-8">

  <!-- Begin Jekyll SEO tag v2.8.0 -->
<title>Logica | Modern Logic Programming</title>
<meta name="generator" content="Jekyll v3.9.3" />
<meta property="og:title" content="Logica" />
<meta property="og:locale" content="en_US" />
<meta name="description" content="Modern Logic Programming" />
<meta property="og:description" content="Modern Logic Programming" />
<link rel="canonical" href="https://logica.dev/" />
<meta property="og:url" content="https://logica.dev/" />
<meta property="og:site_name" content="Logica" />
<meta property="og:type" content="website" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="Logica" />
<meta name="twitter:site" content="logica.dev" />
<meta name="twitter:description" content="Logica : Modern Logic Programming" />
<meta name="twitter:image" content="https://logica.dev/Logica_Logo_16_9.png" />

<script type="application/ld+json">
{"@context":"https://schema.org","@type":"WebSite","description":"Modern Logic Programming","headline":"Logica","name":"Logica","url":"https://logica.dev/"}</script>
<!-- End Jekyll SEO tag -->

  <script src="syntax_highlighting.js"></script>
  <link rel="icon" href="Logica_Icon.png" type="image/png">
  <link rel="stylesheet" href="logica_syntax.css" type="text/css"/>
  <style>
    @import url('https://fonts.googleapis.com/css2?family=Ubuntu:wght@300;400;700&display=swap');
    @import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap');
    @import url('https://fonts.googleapis.com/css2?family=Nunito:wght@400;700;800&display=swap');

    body {
      background-color:#f1f1f1
    }
    .header {
      max-width: 870px;
      margin:10px;
      /*height: auto;*/
      
      display:flex;
      flex-wrap: wrap;

      height: fit-content;
      background-color: #fefefe;
      box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3);
      padding:5px;
      border-radius: 3px;
      text-align: left;
      padding: 20px;
      padding-left: 50px;
      margin-left: auto;
      margin-right: auto;
      padding-top: 30px;
      padding-bottom: 30px;
    }
    .subheader {
      padding-left: 15px;
      float: right;
      margin-left:auto;
      font-size: 20px;
      font-family: 'Ubuntu', sans-serif;
      line-height: 1.5;
    }
    .content {
      max-width: 860px;
      margin:10px;
      height: auto;
      background-color: #fefefe;
      box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3);
      padding-left:40px;
      padding-right:40px;
      padding-top:1px;
      padding-bottom:40px;
      border-radius: 3px;
      margin-left: auto;
      margin-right: auto;
      font-family: 'Nunito', sans-serif;

    }
    div {
      display: block;
    }
    .github_button {
      float: right;
      border: solid 2px;
      margin: 20px;
      padding: 10px;
      margin-top: 30px;
      border-radius: 10px;
      transition: all 0.2s;
      background-image: linear-gradient(-45deg, #fff, #fff, #fff, #eee); /* Add the gradient as an initial background image */
      background-size: 200%;
    }

    .github_button:hover {
      scale: 1.2;
      background-position: 100% 100%;
      box-shadow: 15px 15px 25px rgba(0, 0, 0, 0.3);
    }

    .github_button:active {
      scale: 1.0;
      box-shadow: none;
      transition: all 0.03s;

    }
    .inline_code {
      font-family: monospace;
    }

    @media(max-width: 900px) {
      .subheader {
        float: left;
        margin-left: 0;
      }
    }

    .monospace {
      font-family: monospace;
      font-size:1.2em;
    }

    .larger_code_font {
      font-size: 35px;
    }
  </style>
</head>
<body onload="HighlightCodeElements(document);">
<div class="header">
<img id="logica_logo" src="logica_logo.png" width="500px"/>


<div class="subheader"> <!-- style="width:auto"> -->
  Logic Programming Language  <br/><span style="width: 20px;  display: inline-block;"></span>for Data Analysis
  <!--Logic Programming Language for Data Analysis -->

  <!-- Modern Logic Programming -->
</div>
</div>

<div class="content">
  <div style="float: right; display:flex; flex-direction:column;">
  <a href="https://github.com/evgskv/logica" style="text-decoration: none; color: inherit;">
    <div class="github_button" style="float: none;"  onclick="thumbsUp()">
      <img src="github-mark.png" height="80px"/>
      <div style="float: right; margin: 10px;">
        View project on<br/>
        GitHub. <span id="thumbs_up" style="display:none">😃👍</span>
      </div>
    </div>
  </a>
  <a href="https://logica-lang.github.io/" style="text-decoration: none; color: inherit;">
    <div class="github_button" style="float: none; margin-top: 0px; padding: 5px;" onclick="openBook()">
      <div style="float: none; text-align: center; display: flex; flex-direction: row;">
        <div id="closed_book" style="font-size: 4em; display:flex; margin: 0px; width: 80px; text-align: center; justify-content: center;"><span>📘</span></div>
        <div id="open_book" style="font-size: 4em; display:none; width: 80px; text-align: center; justify-content: center;">📖</div><br/>
        <div style="display: flex; justify-content: center; align-items: center; padding-left: 15px;">
          <div>Documentation</div>
        </div>      
      </div>
    </div>
  </a>
  </div>

<script>
  function thumbsUp() {
    let s = document.getElementById('thumbs_up');
    s.style.display = 'inline'
  }
  function openBook() {
    let s1 = document.getElementById('open_book');
    let s2 = document.getElementById('closed_book');
    s1.style.display = 'flex'
    s2.style.display = 'none'
  }

  function reactToDevice() {
    if (window.screen.width < 400) {
      let code = document.querySelectorAll('.code');
      code.forEach((e) => {
        e.classList.add('larger_code_font');
      });
    }
  }
  // setTimeout(reactToDevice, 500);
</script>
<h1>What is Logica?</h1>

<div>
<p>
  Logica is an <a href="https://github.com/evgskv/logica">open source</a>
  declarative logic programming language for data manipulation.
</p>

<p>
  Logica extends syntax of logic programming for intuitive and efficient data
  manipulation. It compiles to SQL thus providing you access to the power
  of SQL engines with the convenience of logic programming syntax.
</p>

<p>
  Logica can compiles to SQL dialects of DuckDB, SQLite, Google BigQuery and Postgres. This makes
  it practical for a wide range of applications. Almost every computational device comes with SQLite
  and thus you can run Logica there. DuckDB is a powerful on-device computation engine with robust
  SQL semantics that is easy to install and can efficiently leverage parallelism of modern devices.
  Google BigQuery is a distributed datawarehouse capable of processing terabytes of data in seconds
  and PostgreSQL is the most popular open source SQL engine.
  
</p>
<p>
  Thus Logica reaches widely into
  SQL ecosystem and can be employed by professionals willing to stay with the clarity of logic reasoning
  while performing data analysis. 
</p>

</div>
<h1>Examples</h1>


<p>
  One may say that for programming languages like Python and Java functions are the
  basic building blocks. For Logica and other logic programming languages
  those building blocks are <i>predicates</i>. 

  Logic program is defined as a set of rules that define output predicates
  from pre-defied predicates. Those pre-defined predecates represent input data.

  For example here is a rule to identify names of expensive books, from an existing
  table of book prices.
</p>


<div class="code">
# Logica rule to get expensive books.
ExpensiveBook(book_name) :-   # book_name is expensive if and only if
  Book(book_name, price),     # book_name costs price
  price > 100;                # and price is greater than 100.
</div>

<p>
If you are familiar with SQL, you may see that the rule above
is equivalent to the flowing SQL statement. Not that familiarity with SQL is
required to learn Logica, not at all.
</p>

<div class="code">
# SQL statement to get expensive books.
SELECT book_name
FROM book
WHERE price > 100;
</div>

Predicate is a statement with variables. Any table can be treated as predicate,
where column names are the variables, and each row is a set of values of the variables
that satisfies the statement. 

While SQL is quite convenient for small queries like the one above it
gets hard to read when complexity grows. Logica leverages power of
mathematical syntax to scale nicely as complexity grows.

Let's assume we have a table <span style="font-family: monospace">BabyNames</span>
that for each <span style="font-family: monospace">name, year, city</span> and
<span style="font-family: monospace">gender</span> specifies 
<span style="font-family: monospace">number</span> of babies of that name born.
The following program finds a list of <i>popular</i> names, where a name
is defined as popular if it was the most popular name on some year.

<div class="code">
# Count babies per year.
NameCountByYear(name:, year:) += number :-
  BabyNames(name:, year:, number:);
  
# For each year pick the most popular.
TopNameByYear(year) ArgMax= name -> NameCountByYear(name:, year:);

# Accumulate most popular name into a table, droppig the year.
PopularName(name: TopNameByYear());
</div>

Sometimes data analysis requires solving algorithmic problems. Logica's
syntax is suited for it naturally. Here is a program finding prime numbers
that are less than 100.

<div class="code">
# Define numbers 1 to 30.
Number(x + 1) :- x in Range(30);

# Defining composite numbers.
Composite(a * b) distinct :- Number(a), Number(b), a > 1, b > 1;

# Defining primes as "not composite".
Prime(n) distinct :- Number(n), n > 1, ~Composite(n);
</div>

<h2>Cities with largest beer variety</h2>

Let's use beer variety dataset from [plotly](https://github.com/plotly/datasets/blob/master/beers.csv).

Let us find top 5 states with largest variety of beers. In each state we will pick city with the largest
variety in the state.

To run this example you will need to install DuckDB if you don't yet have it on your system. Luckily installing DuckDB is easy:

<div class="code">
python3 -m pip install duckdb
</div>

Program <i>beer.l</i>:

<div class="code">
@Engine("duckdb");

@Ground(Beer);
Beer(..r) :- 
    `('https://github.com/plotly/datasets/blob/master/beers.csv?raw=true')`(..r);

BeersInState(state) += 1 :- Beer(state:);
BeersInCity(state, city) += 1 :- Beer(state:, city:);

ArgMax5(x) = ArgMaxK(x, 5);
BestCityForBeer(state:, city:,
                city_beers: BeersInCity(state, city),
                state_beers: BeersInState(state)) :-
    state in ArgMax5{s -> BeersInState(s)},
    city = ArgMax{c -> BeersInCity(state, c)};
</div>

Running <i>beer.l</i>:

<div class="code">
# logica beer.l run BestCityForBeer
+-------+--------------+------------+-------------+
| state | city         | city_beers | state_beers |
+-------+--------------+------------+-------------+
| IN    | Indianapolis | 43         | 139         |
| CO    | Boulder      | 41         | 265         |
| CA    | San Diego    | 42         | 183         |
| TX    | Austin       | 25         | 130         |
| MI    | Grand Rapids | 66         | 162         |
+-------+--------------+------------+-------------+
</div>


<!--
<p>
Finally here is an example of program that runs over
<a href="https://www.gdeltproject.org/">GDELT Project</a> dataset,
finding people mentioned in the context of "artificial general intelligence".
</p>


<p>Observe that program is divided into a rule defining predicate
  <span class="monospace">NewsData</span> and rule for <span class="monospace">AgiMentions</span>.
The first rule is essentially doing data cleaning, formatting the dataset in a shape
that is convenient to use. Then second rule peforms the task at hand.
</p>

<p>
In Logica problems are naturally split into smaller components that end up
reusable. So in the future if we have more analysis to do with GDELT dataset
we may take advantage of the <span class="monospace">NewsData</span> predicate that we just wrote.
</p>

<div class="code">
# Structuring the data conveniently.
NewsData(year:, month:, day:, persons:, quotations:) :-
  gdelt-bq.gdeltv2.gkg(persons: persons_str, quotations:, date: date_num),
  # Column `data` in GDELT dataset is given as an integer.
  year == ToInt64(Substr(ToString(date_num), 1, 4)),
  month == ToInt64(Substr(ToString(date_num), 5, 2)),
  day == ToInt64(Substr(ToString(date_num), 7, 2)),
  persons List= (person :- person in Split(persons_str, ";"));

# Performing the task at hand.
@OrderBy(AgiMentions, "mentions desc");
@Limit(AgiMentions, 10);
AgiMentions(person:, mentions? += 1) distinct :-
  person in persons,
  Like(quotations, "%artificial general intelligence%"),
  NewsData(persons:, quotations:);

</div>

This program completes in interactive time
when ran over the 4TB dataset
via BigQuery.
-->

<div>
  <h1> Why Logica? </h1>

Logica is for engineers, data scientists and other specialists who 
need to perform complex data processing and analysis.
Queries and pipelines written in Logica can run on
<a href="https://cloud.google.com/bigquery">BigQuery</a>, <a href="https://sqlite.org/index.html">SQLite</a>
and <a href="https://www.postgresql.org/">PostgreSQL</a> engines.
Information stored in these systems is thus available in Logica.


<p>
Logica compiles to SQL and gives you access to the power of SQL engines,
including the massively distrbuted Google BigQuery engine,
with the convenience of logic programming syntax. This is useful because
BigQuery is magnitudes more powerful than state of the art native
logic programming engines.
</p>

<p>
We encourage you to try Logica, especially if
</p>

<ul>
  <li>   you already use logic programming and need more computational power, or </li>
  <li>   you already have data in BigQuery, PostgreSQL or SQLite, or </li>
  <li>   you want to learn logic programming and apply it to processing of Big Data.</li>
</ul>

Among other engines, there is partial support for Trino and Databricks.
Contributions to improve this support are
<a href="https://github.com/EvgSkv/logica/discussions">very welcome</a>!

</div>

<h1> I have not heard of logic programming. What is it? </h1>

<p>
Logic programming is a declarative programming paradigm where the program is
written as a set of logical statements.
</p>

<p>
Logic programming was developed in academia from the late 60s. Prolog and
Datalog are the most prominent examples of logic programming languages. 
Logica is a successor to
<a href="https://research.google/pubs/pub43462/">Yedalog</a>,
a language created at Google earlier. Logica as well as Yedalog belong to
Datalog family.
</p>

<p>
Datalog and relational databases start from the same idea: think of data
as relations and think of data manipulation as a sequence of operations over
these relations. But Datalog and SQL differ in how these operations are
described. Datalog is inspired by the mathematical syntax of the first order
propositional logic and SQL follows the syntax of natural language.
</p>

<p>
SQL was based on the natural language to give access to databases to the people
without formal training in computer programming or mathematics. This convenience
may become costly when the logic that you want to express is non trivial.
There are many examples of hard-to-read SQL queries that correspond to simple
logic programs.
</p>

<p>
Logica follows Yedalog in the attempt to merge these branches back together:
extending the elegant syntax of Logic Programming to solve practical problems
and leverage the tremendous advances of SQL infrastructure for the execution.
</p>


<h1>How does Logica work?</h1>

Logica compiles the logic program into a SQL expression,
so it can be executed on BigQuery, the state of the art SQL engine.

Among database theoreticians Datalog and SQL are known to be equivalent.
And indeed the conversion from Datalog to SQL and back is often straightforward.
However there are a few nuances, for example how to treat disjunction and negation. In Logica we tried to make choices that make understanding of the resulting SQL structure as easy as possible, thus empowering user to write programs that are executed efficiently.

<h1>Why is it called Logica?</h1>

Logica stands for <b>Logic</b> with <b>a</b>ggregation.

<div style="display: flex; align-items: flex-start;">
  <h1>How to learn?</h1>

  <a style="text-decoration: none; color: inherit;margin-left: auto;" href="sandbox.html">
    <div class="github_button" style="font-size:150%" onclick="graduate2()" >
      <span style="display:inline-block;" id="hat2">🏖️</span> <span style="display:none" id="grad2">🏐</span> Playground 
    </div>
  </a>

  <a style="text-decoration: none; color: inherit;" href="https://colab.research.google.com/github/EvgSkv/logica/blob/main/tutorial/Logica_DuckDB_tutorial.ipynb">
    <div class="github_button" style="font-size:150%" onclick="graduate()" >
      <span style="display:inline-block;" id="hat">🎓</span> <span style="display:none" id="grad">👨‍🎓</span> Tutorial 
    </div>
  </a>
  <script>
  function graduate() {
    let g1 = document.getElementById('hat');
    let g2 = document.getElementById('grad');
    g1.style.display = 'none'
    g2.style.display = 'inline-block'
  }
  function graduate2() {
    let g1 = document.getElementById('hat2');
    let g2 = document.getElementById('grad2');
    g1.style.display = 'none'
    g2.style.display = 'inline-block'
  }
  </script>
</div>

<p>
Learn basics of Logica with the
<a href="https://colab.research.google.com/github/EvgSkv/logica/blob/main/tutorial/Logica_tutorial.ipynb">CoLab tutorial</a> 
located at <a href="https://github.com/EvgSkv/logica/tree/main/tutorial">tutorial</a> folder.
See <a href="https://github.com/EvgSkv/logica/tree/main/examples">examples</a> of using Logica in examples folder.

You try Logica immediately in the browser in <a href="sandbox.html">Playground</a>.
</p>

<p>
It is easy to install Logica on your machine as well.
</p>

<h1>Installation</h1>

Install Logica with `pip`.

<div class="code">
# Install:
$ python3 -m pip install logica
# Run:
$ python3 -m logica
# (optional) Create alias for convenience:
alias logica=python3 -m logica
</div>

Let's say this program is written in file
 <span style="font-family: monospace">hello.l</span>.
<div class="code">
@Engine("sqlite");
Greeting("Hello world!");
</div>

When exectued with

<div class="plain_code">
$ logica hello.l run Greeting
</div>

it should produce the following table:<br/>

<div class="plain_code" style="width:fit-content">
+--------------+
|     col0     |
+--------------+
| Hello world! |
+--------------+
</div>


<h1>Join the discussion!</h1>

If you have any questions or ideas about Logica, you
are welcome to post those in <a href="https://github.com/EvgSkv/logica/discussions">Discussions section</a> of the repo!



<div style="margin-top: 50px"></div>
<p style="font-style: italic;">
Unless otherwise noted, the Logica source files are distributed under the Apache 2.0 license found in the LICENSE file.
</p>
<p  style="font-style: italic;">
Logica is not an officially supported Google product.
</p>

</div>  <!-- End of Content -->

</body>
